package main

import "fmt"

//接口是用来定义行为的类型。
type notifier interface {
	//这些被定义的行为不由接口直接实现
	//而是通过方法由用户定义的类型实现
	notify()

	/*
		接口值是一个两个字长度的数据结构
		第一个字包含一个指向内部表（iTable）的指针,包含了所存储的值的类型信息
			iTable包含了已存储的值类型信息以及这个值相关联的一组方法
				1. 值类型 或 指向保存类型的指针
				2. 方法集：定义了一组关联到给定类型的值或指针的方法
		第二个字是一个指向所存储值的指针。

	*/
}

type user struct {
	name  string
	email string
}

// 指针接收者实现的方法
func (u user) notify() {
	fmt.Printf("Sending user email to %s<%s>\n", u.name, u.email)
}

/*
如果使用指针接收者实现一个接口，那么只有指向那个类型的指针才能实现对应的接口。
如果使用值接收者来实现一个接口，那么那个类型的值和指针都能够实现对应的接口
*/

// 接收一个实现了notifier接口的值
func sendNotification(n notifier) {
	n.notify()
}

func main() {
	u := user{"Bill", "bill@email.com"}

	sendNotification(u)
	sendNotification(&u)

}
